#region License
/* ---------------------------------------------------------------- *
 *
 * This file is part of the Xcoordination Application Space
 * ("XcoAppSpace") http://www.xcoordination.com
 *
 * Copyright (C) 2009 Xcoordination http://www.xcoordination.com
 *
 * XcoAppSpace is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General
 * Public License as published by the Free Software Foundation.
 *
 * XcoAppSpace is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/
 * or write to the Free Software Foundation, Inc., 51 Franklin
 * Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * ---------------------------------------------------------------- */
#endregion

using System;
using System.ServiceModel.Channels;
using Microsoft.ServiceBus;
using System.Configuration;

namespace XcoAppSpaces.Transport.WCF
{
    /// <summary>
    /// Helper for the Azure bindings
    /// </summary>
    public class BindingsHelperAzure : IBindingsHelper
    {

        private const string XcoPortStr = "xco";

        /// <summary>
        /// Creates a new XcoAzureTransportService.
        /// </summary>
        public BindingsHelperAzure()
        {
            LoadServiceNameSpace();
        }

        /// <summary>
        /// Load the Azure namespace from the config 
        /// </summary>
        private static void LoadServiceNameSpace()
        {
            if (serviceNamespace == null)
            {
                serviceNamespace = ConfigurationManager.AppSettings["XcoAzureServiceNamespace"];
				//if (!string.IsNullOrEmpty(serviceNamespace))
				//{
				//    if (!serviceNamespace.EndsWith("/"))
				//    {
				//        serviceNamespace += "/";
				//    }
				//}
            }
        }


        private static string serviceNamespace;
        private BindingsHelper helper = new BindingsHelper();
        /// <summary>
        /// Currently used binding scheme
        /// </summary>
        public Binding usedBindingScheme;

        /// <summary>
        /// Not needed for Azure services
        /// </summary>
        /// <param name="port">The port that should be used</param>
        /// <returns>null, not used</returns>
        public Uri GenerateStandardNetTcp(int port)
        {
            return null;
        }

        /// <summary>
        /// Generates a Azure address
        /// </summary>
        /// <param name="address">The address that should be used for the service</param>
        /// <returns></returns>
        public string Convert(string address)
        {
            return Convert(usedBindingScheme, address).ToString();
        }

        /// <summary>
        /// Generates a binding url for a Azure service 
        /// </summary>
        /// <param name="bindingType">The binding that should be used</param>
        /// <param name="address">The address that should be used for the service</param>
        /// <returns>Uri for Azure service</returns>
        public Uri Convert(Binding bindingType, string address)
        {
            if (usedBindingScheme == null)
            {
                usedBindingScheme = bindingType;
            }
            if (bindingType is NetTcpRelayBinding)
            {
                return ConvertNetTcpRelay(address);
            }
            return helper.Convert(bindingType, address);
        }
        /// <summary>
        /// Returns the server address without the Azure main adress
        /// </summary>
        /// <param name="addr">Uri Azure adress for convert</param>
        /// <returns>Server address without the Azure main adress</returns>
        public string ServerAddr(Uri addr)
        {
            if (usedBindingScheme is NetTcpRelayBinding)
            {
				return addr.ToString(); //addr.Segments[addr.Segments.Length - 1];
            }
            else
            {
                return helper.ServerAddr(addr);
            }
        }

        /// <summary>
        /// Read the port part from the Azure address
        /// </summary>
        /// <param name="addr">Uri Azure adress for convert</param>
        /// <returns>The port of the Azure address</returns>
        public int Port(Uri addr)
        {
            if (addr.Scheme == "sb")
            {
                string portStr = addr.Segments[addr.Segments.Length - 1];
                if (portStr.StartsWith(XcoPortStr))
                {
                    portStr = portStr.Substring(XcoPortStr.Length, portStr.Length - XcoPortStr.Length);
                    portStr = portStr.Replace("/", "");
                    int port;
                    if (int.TryParse(portStr, out port))
                    {
                        return port;
                    }
                }
            }
            return helper.Port(addr);
        }

        /// <summary>
        /// Generates a Azure Service Uri with Azure Namespace
        /// </summary>
        /// <param name="port">The port of the Azure address</param>
        /// <returns>Address for the Azure Service</returns>
        public static string GenerateUri(int port)
        {
            LoadServiceNameSpace();
			if (string.IsNullOrEmpty(serviceNamespace)) //when only a port is used a service namespace is needed - throw error if it has not been configured
				throw new ArgumentException("No namespace has been defined in app.config. You must configure a namespace when using the XcoAzureTransportService with a port.");

            var uri = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, XcoPortStr + port).ToString();
			return uri;
        }

        /// <summary>
        /// Generates an Uri for the Azure service
        /// </summary>
        /// <param name="address">The address that should be used for the Azure service</param>
        /// <returns>Uri for the Azure service</returns>
        private Uri ConvertNetTcpRelay(string address)
        {
			if (address.StartsWith("sb://", StringComparison.OrdinalIgnoreCase))
				return new Uri(address); //this is already a complete address - so just use it

			if (string.IsNullOrEmpty(serviceNamespace)) //for incomplete address a service namespace is needed - throw error if it has not been configured
				throw new ArgumentException("Address \"" + address + "\" is incomplete, and no namespace has been defined in app.config. You must either use a complete address or a configure a namespace.");

            return ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, address);
        }
    }
}